package com.mao.interview.lock;

import java.io.IOException;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 利用JMC工具检查线程的状态转换
 *
 */
public class ThreadStateTest {

	/**
	 * 测试阻塞状态--> 1:main线程显示TIMED_WAITING状态, 2:test线程显示BLOCKED状态, 3:main线程先执行
	 * 结论：synchronized尝试获取对象锁失败后，线程进入BLOCKED状态; sleep操作进入TIMED_WAITING状态
	 */
	public static void testSynchronized() throws InterruptedException {
		Object lock = new Object();
		Thread t = new Thread("test") {

			@Override
			public void run() {
				synchronized (lock) {

				}
			}

		};
		synchronized (lock) {
			t.start();
			Thread.sleep(Integer.MAX_VALUE);
		}
	}

	/**
	 * 测试等待状态--> 1:main线程显示TIMED_WAITING, 2:test线程显示BLOCKED状态
	 * Thread.interrupted是一种检测标志,被中断的线程也只能等到重新获得对象锁后响应中断
	 * Object.wait不影响Thread因synchronized进入的BLOCKED状态
	 */
	public static void testWaiting0() throws InterruptedException {
		Object lock = new Object();
		Thread t = new Thread("test") {

			@Override
			public void run() {
				synchronized (lock) {
					try {
						lock.wait(3000);
					} catch (InterruptedException e) {
						System.out.println("test线程响应中断的时间：" + new Date());
					}
				}
			}

		};
		t.start();
		Thread.sleep(1000);
		synchronized (lock) {
			// System.out.println("打断test的时间：" + new Date());
			// t.interrupt();
			Thread.sleep(10000);
			lock.notifyAll();
			Thread.sleep(Integer.MAX_VALUE);
		}
	}

	/**
	 * 使用 Lock类上锁则是进入WAITING状态
	 */
	public static void testWaiting1() throws InterruptedException {
		ReentrantLock lock = new ReentrantLock();
		Thread t = new Thread("test") {
			@Override
			public void run() {
				try {
					lock.lockInterruptibly();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				lock.unlock();
			}
		};
		lock.lock();
		t.start();
		Thread.sleep(Integer.MAX_VALUE);
		lock.unlock();
	}

	/**
	 * 还是WATING状态，Condition的使用不影响这个状态类型 修改main线程signalAll后的睡眠发现
	 * 同时还发现，main线程打断了test，但是test没有从异常中返回！
	 */
	public static void testWaiting2() throws InterruptedException {
		ReentrantLock lock = new ReentrantLock();
		Condition condition = lock.newCondition();
		Thread t = new Thread("test") {
			@Override
			public void run() {
				lock.lock();
				try {
					// condition.await();
					condition.await(5000, TimeUnit.SECONDS);
				} catch (InterruptedException e) {
					System.out.println("test线程响应中断的时间：" + new Date());
				}
				lock.unlock();
			}
		};
		t.start();
		Thread.sleep(1000);
		lock.lock();
		System.out.println("打断test的时间：" + new Date());
		t.interrupt();
		condition.signalAll();
		Thread.sleep(Integer.MAX_VALUE);
		lock.unlock();

	}

	public static void testWaiting3() throws InterruptedException {
		Object lock = new Object();
		Thread t = new Thread("test") {

			@Override
			public void run() {
				synchronized (lock) {
					try {
						lock.wait();
					} catch (InterruptedException e) {
						System.out.println("test线程响应中断的时间：" + new Date());
					}
				}
			}

		};
		t.start();
		Thread.sleep(1000);
		synchronized (lock) {
			Thread.sleep(3000);
		}
		Thread.sleep(Integer.MAX_VALUE);
	}

	public static void testWaiting4() throws InterruptedException {
		Object lock = new Object();
		Thread t = new Thread("test") {

			@Override
			public void run() {
				synchronized (lock) {
					try {
						lock.wait(20000);
					} catch (InterruptedException e) {
						System.out.println("test线程响应中断的时间：" + new Date());
					}
				}
				System.out.println("test结束");
			}

		};
		t.start();
		Thread.sleep(1000);
		synchronized (lock) {
			Thread.sleep(2000);
		}
		Thread.sleep(Integer.MAX_VALUE);
	}

	/**
	 * 线程使用Block I/O等待外部资源时，显示的RUNNABLE状态
	 */
	public static void testBlocked() {
		Thread t = new Thread("test") {

			@Override
			public void run() {
				try {
					System.in.read();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		};
		t.start();
		LockSupport.park();
	}

	public static void main(String[] args) throws Exception {
		// testSynchronized();
		// testWaiting0();
		// testWaiting0();
		// testWaiting2();
		// testWaiting3();
		// testWaiting4();
		testBlocked();
	}
}
